package common;

import static junit.framework.Assert.*;

import java.io.*;
import java.util.*;

import msg.*;

import org.junit.*;

import registration.RegistrationManager;
import user.*;

import common.dal.*;
import common.logger.*;
import common.logger.Logger.LogLevel;

@SuppressWarnings({"static-method", "javadoc"})
public abstract class DALTests {
	protected static final Logger	logger		= CompositeLogger.getInstance();
	private static User				_user;
	private static User				_fakeUser;
	private static EventMessage		_event;
	private static EventMessage		_fakeEvent;
	protected static final String	PASSWORD	= "rosebud";
	
	protected static final Location	haifa		= new Location(32.8, 34.983333, "Haifa");
	protected static final Location	netanya		= new Location(32.3333, 34.8500, "Netanya");
	protected static final Location	telAviv		= new Location(32.0833, 34.8000, "Tel-Aviv");
	protected static final Location	SW_MAX		= new Location(-90, -180, "END OF THE WORLD");
	protected static final Location	NE_MAX		= new Location(90, 180, "THE OTHER END OF THE WORLD");
	static {
		Properties props = new Properties();
		try {
			props.load(new FileInputStream(new File("./tests/tests.properties")));
			Configuration.getInstance().setProps(props);
			Creator.createDB(props);
		} catch (Exception e) {
			throw new AssertionError(e);
		}
	}
	
	@BeforeClass
	public static void setupBeforeClass() throws Exception {
		t = new Transaction();
		logger.log(LogLevel.INFO, "setting up");
		RegistrationManager.getNewInstance(t).drop();
		MessageManager.getNewInstance(t).drop();
		LoginManager.getNewInstance(t).setup();
		MessageManager.getNewInstance(t).setup();
		RegistrationManager.getNewInstance(t).setup();
		
		_user = LoginManager.getNewInstance(t).registerUser("a" + new Date().getTime() + "", "name", PASSWORD);
		_fakeUser = LoginManager.getNewInstance(t).registerUser(_user.getId() + "_", "name", PASSWORD);
		_event = MessageManager.getNewInstance(t)
				.createNewEventMessage(new Location(0, 0), "", _user, getTomorrow(), 10);
		_fakeEvent = MessageManager.getNewInstance(t)
				.createNewEventMessage(new Location(0, 0), "", _user, getTomorrow(), 1);
		LoginManager.getNewInstance(t).deleteUser(_fakeUser.getLogin(), PASSWORD);
		MessageManager.getNewInstance(t).delete(_fakeEvent.getId());
		t.commit();
	}
	
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		t = new Transaction();
		logger.log(LogLevel.INFO, "tearing down");
		// t.pool.commitAll();
		RegistrationManager.getNewInstance(t).drop();
		MessageManager.getNewInstance(t).drop();
		LoginManager.getNewInstance(t).drop();
		t.commit();
	}
	
	protected static Transaction	t;
	
	@Before
	public void setup() throws Exception {
		t = new Transaction();
		logger.log(LogLevel.DEBUG, "----------------------------------------------");
	}
	
	@After
	public void tearDown() throws Exception {
		t.commit();
	}
	
	/**
	 * @return the uSER
	 */
	protected static User getUser() {
		return _user;
	}
	
	/**
	 * @return the fAKE_USER
	 */
	protected User getFakeUser() {
		return _fakeUser;
	}
	
	/**
	 * @return the event
	 */
	protected EventMessage getEvent() {
		return _event;
	}
	
	/**
	 * @return the fakeEvent
	 */
	protected EventMessage getFakeEvent() {
		return _fakeEvent;
	}
	
	public static Calendar getTomorrow() {
		final Calendar manyana = Calendar.getInstance();
		manyana.add(Calendar.DAY_OF_MONTH, 1);
		return manyana;
	}
	
	protected static void assertThrows(IExceptionRunnable runnable, Class<?> excetionClass) {
		try {
			runnable.run();
			fail("exception not thrown");
		} catch (Exception e) {
			Assert.assertTrue("incorrect exception thrown", excetionClass.isAssignableFrom(e.getClass()));
		}
	}
}
